package view.actionListeners;

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JLabel;
import javax.swing.JOptionPane;

import controller.Controller;

import view.AddPiecePanel;
import view.FrameManager;
import view.SetGameModes;

/**
 * Class implements a listener for button to add a piece to the board
 */
public class AddPieceListener implements ActionListener {

	// members	
	private static final String white = "White";
	private static final String black = "Black";
	private AddPiecePanel piecePanel;
	private Controller gameManager;
	private FrameManager frameManager;
	private SetGameModes gameModeMngr;
	private int firstPlayerPieceCtr;
	private int secondPlayerPieceCtr;
	private int maxPieces;
	private boolean isFirstPlayerPiece;
	private boolean firstCannotAdd;
	private boolean secondCannotAdd;
	private String confirmCmnd;
	private String doneCmnd;
	private JLabel currentPlayer;
	
	// private methods
	
	/**
	 * Updates data necessary for tracking each player's piece adding.
	 * If current player has exceeded maximal piece number, function prevents player from adding any more pieces 
	 */
	private void updatePieceCounter() {
		
		// check if should handle first player
		if (isFirstPlayerPiece) {
			
			// check if had not exceeded maximal piece number
			if (++firstPlayerPieceCtr >= maxPieces) {

				// cannot add any more pieces
				firstCannotAdd = true;
			}
		}
		
		// check if second player had not exceeded maximal piece number
		if (++secondPlayerPieceCtr >= maxPieces) {

			// cannot add any more pieces
			secondCannotAdd = true;
		}
	}
	
	/**
	 * Updates indicator for the current player to add pieces.
	 * If the next player cannot add any more pieces, players are not switched
	 */
	private void updateCurrentPlayer() {
		
		// check if current player is the first
		if (isFirstPlayerPiece) {
			
			// check if second player can add any more pieces
			if (!secondCannotAdd) {
				
				// can add, switch players
				isFirstPlayerPiece = !isFirstPlayerPiece;
				
				// update color label
				currentPlayer.setText(black);
			}
			
		} else { // current player is the second
			
			// check if first player can add any more pieces
			if (!firstCannotAdd) {
				
				// can add, switch players
				isFirstPlayerPiece = !isFirstPlayerPiece;
				
				// update color label
				currentPlayer.setText(white);
			}
		}		
	}
	
	/**
	 * Notifies user that adding pieces has ended. 
	 * Then removes the piece adding panel from the frame and sets the game
	 */
	private void endAdding() {
			
		// done adding, notify user
		JOptionPane.showMessageDialog(null, "Enjoy your game :)", "Done adding pieces", JOptionPane.INFORMATION_MESSAGE);
		
		// remove panel
		frameManager.removePanel(piecePanel);
		
		// update change on frame
		frameManager.validateFrame();
		
		// board is ready, set game mode
		gameModeMngr.setPartialGame();
	}
	
	/**
	 * Adds piece according to selected type and position. 
	 */
	private void addPiece() {
		
		// get piece type
		String type = piecePanel.getSelectedPiece();
		
		// get piece position
		Point position = new Point(piecePanel.getRowIndex(), piecePanel.getColIndex());
		
		if (type != null) {
			
			// add piece to system
			boolean canAdd = gameManager.addPiece(position, type, isFirstPlayerPiece);
			
			if (!canAdd) {
				// notify that position is occupied 
				JOptionPane.showMessageDialog(null, "There is another piece at this position!", "Position Conflict", JOptionPane.ERROR_MESSAGE);
				return;
			}
			
			// place piece on board
			frameManager.setButtonIcon(type, position, isFirstPlayerPiece);
			
			// update piece counter
			updatePieceCounter();
			
			// update current player
			updateCurrentPlayer();

			// check if both players are done adding pieces
			if (firstCannotAdd && secondCannotAdd) {
				
				// both players are done, end adding
				endAdding();			
			}
		}
	}
	
	/**
	 * Marks that current player is done adding pieces.
	 * If both players have already done adding pieces, ends adding
	 */
	private void playerIsDone() {
		
		// current player will not add any more pieces
		if (isFirstPlayerPiece) {
			firstCannotAdd = true;
		} else {
			secondCannotAdd = true;
		}
		
		// update current player
		updateCurrentPlayer();
		
		// check if both players are done adding pieces
		if (firstCannotAdd && secondCannotAdd) {
			endAdding();			
		}		
	}
	
	// public methods
	
	/**
	 * Constructor- creates a new action listener
	 * @param piecePanel- panel to add pieces
	 * @param gameManager- reference to game manager
	 * @param frameManager- reference to game display's frame manager
	 * @param maxPieces- maximal number of pieces for each player
	 * @param confirmCmnd- command string for Confirm button
	 * @param doneCmnd- command string for Done button
	 * @param currentPlayer- indicates for which player should add current piece
	 * @param gameModeMngr- used to set the partial game
	 */
	public AddPieceListener(AddPiecePanel piecePanel, Controller gameManager, FrameManager frameManager, int maxPieces, String confirmCmnd, String doneCmnd, JLabel currentPlayer, SetGameModes gameModeMngr) {
		
		// set members according to given value
		this.piecePanel = piecePanel;
		this.gameManager = gameManager;
		this.frameManager = frameManager;
		this.maxPieces = maxPieces;
		this.confirmCmnd = confirmCmnd;
		this.doneCmnd = doneCmnd;
		this.currentPlayer = currentPlayer;
		this.gameModeMngr = gameModeMngr;
		
		// initialize piece counter for each player
		firstPlayerPieceCtr = 0;
		secondPlayerPieceCtr = 0;
		
		// first player starts adding pieces
		isFirstPlayerPiece = true;
		
		// both players can add pieces
		firstCannotAdd = false;
		secondCannotAdd = false;
	}
	
	/**
  	 * Handles clicked action- adding a piece or done adding for current player.
  	 * After done adding pieces, sets partial game so the game could start
	 */
	@Override
	public void actionPerformed(ActionEvent event) {

		// check if should add a piece
		if (event.getActionCommand().equals(confirmCmnd)) {
			addPiece();
			return;
		}
		
		// check if current player is done adding pieces
		if (event.getActionCommand().equals(doneCmnd)) {			
			playerIsDone();
			return;
		}
	}
}